import cn from 'classnames';
import PropTypes from 'prop-types';
import React, { useEffect, useMemo, useState } from 'react';
import fetchFer from 'API/fetch';
import Empty from '../../../../../components/empty/EmptyData';
import Table from '@knownsec/react-component/dist/Table';
import { millisecond } from '../../../../../../common/formatter';
import Dialog from '@knownsec/react-component/dist/Dialog';
import Tooltip from '@knownsec/react-component/dist/Tooltip';
import Icon from '@knownsec/react-component/dist/Icon';
import Form from '@knownsec/react-component/dist/Form';
import Datetime from '@knownsec/react-component/dist/Datetime';
import Pagination from '@knownsec/react-component/dist/Pagination';
import Select from '@knownsec/react-component/dist/Select';
import Loading from '@knownsec/react-component/dist/Loading';
import TaskResult from '../../../../../components/AviliableTaskResult';
import CopyBoard from '../../../../../components/CopyBoard';
import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
import { Link } from 'react-router-dom';

import s from './style.module.css';
import moment from 'moment';
import ms from 'ms';
import { turnToUrlparam } from '../../../../../helpers/getUrlParams';
import { cloneDeep } from 'lodash';
import { FREQUENCY_UNIT_MAP as UNIT } from '../../../../../../common/constants';
const defaultFilter = {
	page: 1,
	limit: 10,
};
function InfoTable({ className, tasks, jobId, target }) {
	const resD = JSON.parse(sessionStorage.resD).feature;
	const aviliableNode = JSON.parse(sessionStorage.aviliableNode) || null;
	const allNode = aviliableNode?.v4_area?.concat(aviliableNode?.v6_area).reduce((t, i) => {
		const item = JSON.parse(JSON.stringify(i));
		delete item.enable;
		t[Object.keys(item)[0]] = item[Object.keys(item)[0]];
		return t
	}, {})
	const minDate =
		JSON.parse(sessionStorage.getItem('resD'))?.balance?.aviliableMaxHistory
			?.total || 60;
	const [visible, setVisible] = useState(false);
	const [httpData, setHttpData] = useState([]);
	const [pingData, setPingData] = useState([]);
	const [loading, setLoading] = useState(false);
	const [taskSettings, setTaskSettings] = useState(null);
	const [filter, setFilter] = useState(defaultFilter);
	const [total, setTotal] = useState(0);
	const columns = [
		{
			title: '任务名称',
			dataIndex: 'name',
			key: 'name',
			render(e, row) {
				return row.task_settings.name;
			},
		},
		{
			title: '监测目标',
			dataIndex: 'name',
			key: 'name',
			render(e, row) {
				return (
					<CopyBoard
						className={s.db}
						text={row.overview.target_url}
					></CopyBoard>
				);
			},
		},
		{
			title: '响应正常节点',
			dataIndex: 'node',
			key: 'node',
			render(e, row) {
				return `${
					row.addition?.nodeTotalCount - row.addition?.nodeAbnormalCount < 0
						? 0
						: row.addition?.nodeTotalCount - row.addition?.nodeAbnormalCount
				}/${row.settingsNodeNum}`;
			},
		},
		{
			title: '平均响应时间',
			dataIndex: 'respAvg',
			key: 'respAvg',
			render(e, row) {
				return millisecond(row.addition?.respAvg);
			},
		},
		{
			title: '监测结果',
			dataIndex: 'securityStatus',
			key: 'securityStatus',
			width: 100,
			render(e) {
				return (
					<span
						className={cn({
							[s.errorColor]: ['warning', 'error'].includes(e),
							[s.successColor]: e === 'safe',
						})}
					>
						{e === 'warning' ? '异常' : e === 'error' ? '节点出错' : '正常'}
					</span>
				);
			},
		},
		{
			title: '监测完成时间',
			dataIndex: 'endTime',
			key: 'endTime',
			// width: 280,
			render(e, row) {
				return moment(row?.time_info?.end_time).format('YYYY-MM-DD HH:mm:ss');
			},
		},
	];
	const timeChange = value => {
		let unit;
		let num;
		if (value) {
			const freq = ms(value);
			unit = value ? freq.replace(/\d*/, '') : 'd';
			num = parseInt(freq.replace(/[a-zA-Z]/, ''), 10);
			if (value % ms('30d') === 0) {
				unit = 'month';
				num = value / ms('30d');
			} else if (value % ms('1w') === 0) {
				unit = 'w';
				num = value / ms('1w');
			}
		}
		return `${num}${UNIT[unit] || '毫秒'}`;
	};

	const getData = async date => {
		setLoading(true);
		const http = tasks.http_result_status.map(e => {
			const [id, status] = Object.entries(e)[0]
			if (status) {
				return fetchFer(`/api/v2/tasks/web_security/type/detail?task_id=${id}`, {
					method: 'GET',
					checkStatus: 501,
				}).then(e => {
					return e;
				});
			}
		}).filter(i => i);
		const ping = tasks.ping_result_status.map(e => {
			const [id, status] = Object.entries(e)[0]
			if (status) {
				return fetchFer(`/api/v2/tasks/web_security/type/detail?task_id=${id}`, {
					method: 'GET',
					checkStatus: 501,
				}).then(e => {
					return e;
				});
			}
		}).filter(i => i);
		const resH = await Promise.all(http).catch(e => {
			return [];
		});
		const resP = await Promise.all(ping).catch(e => {
			return [];
		});
		const resHP = [[], []];
		[resH, resP].forEach((res, i) => {
			if (res.length > 0) {
				res.forEach(item_ => {
					const item = item_.data;
					if (item) {
						const settingsIPv4 = item?.task_settings?.collect?.area?.map(i => { return { node: i, networkDisplayName: 'IPv4' } }) || []
						const settingsIPv6 = item?.task_settings?.collect?.area_ipv6?.map(i => { return { node: i, networkDisplayName: 'IPv6' } }) || []
						const res = Object.values(item?.addition?.detail?.concat(settingsIPv4)?.concat(settingsIPv6)?.reduce((total, item) => {
							if (!total[`${item.node}_${item.networkDisplayName}`]) {
								if (!item.area) {
									item.area = allNode[item.node]
									item.securityStatus = 'error'
								}
								total[`${item.node}_${item.networkDisplayName}`] = item
							}
							return total
						}, {}) || {})
						item.addition.detail = res
						item.settingsNodeNum = res.length
						item.securityStatus =
							item.addition.nodeAbnormalCount === 0 ? 'safe' : 'warning';
						item.key = item.task_id;
						item.taskType = i > 0 ? 'ping' : 'http';
						resHP[i].push(item);
					}
				});
			} else {
				resHP[i] = [];
			}
		});
		setHttpData(resHP[0] || []);
		setPingData(resHP[1] || []);
		setLoading(false);
	};
	const handleChangeSearch = e => {
		e && setFilter({ ...filter, ...e });
	};
	const taskContent = (data, map, text) => {
		let res = '- -';
		if (data?.length > 0) {
			if (data.length > 1) {
				res = (
					<>
						{data
							.slice(0, 1)
							.map(item => {
								return map[item];
							})
							.join(', ')}
						等{data.length}个监测节点
						<Tooltip
							overlay={
								<div
									style={{
										maxWidth: '300px',
										maxHeight: '200px',
										overflow: 'auto',
									}}
								>
									{data
										.map(item => {
											return map[item];
										})
										.join(', ')}
								</div>
							}
							placement={'top'}
						>
							<Icon
								type={'detail'}
								className={cn(s.primaryColor, s.cp, s.ml5, s.vam)}
							/>
						</Tooltip>
					</>
				);
			} else {
				res = data
					.slice(0, 1)
					.map(item => {
						return map[item];
					})
					.join(', ');
			}
		}
		return res;
	};
	const checkData = type => {
		let text = '暂无数据';
		let img = 'noData';
		if (!tasks[`${type}_result_id`][0]) {
			if (!resD[`${type}Task`]) {
				text = '当前套餐不支持该监测项，请先升级套餐。';
				img = 'noPrmission';
			} else if (tasks[`${type}_task_checked`] === 0) {
				text = (
					<span>
						该资产未启用该监测项，您可前往“任务管理 -
						<Link
							to={{
								pathname: '/job-manage/create-job',
								search: `assetType=aviliable&jid=${jobId}&aviType=${type}`,
							}}
						>
							可用性监测
						</Link>
						”下发监测任务。
					</span>
				);
				img = 'dataLoading';
			}
		} else {
			const allStatus = tasks[`${type}_result_status`]?.reduce((t, i) => {
				const [id, status] = Object.entries(i)[0]
				if (status) t++
				return t
			}, 0)
			if (tasks[`${type}_result_status`]?.length > 0 && !allStatus) {
				text = '任务数据已过期，您可重新下发监测任务'
			}
		}
		return { img, text };
	};
	const historyPageData = useMemo(() => {
		const res = httpData.reduce((total, item) => {
			let i = cloneDeep(item);
			if (
				filter.securityStatus &&
				item.securityStatus !== filter.securityStatus
			) {
				i = null;
			}
			if (i) total.push(i);
			return total;
		}, []);
		let resultList = [];
		const limit = filter.limit || 10;
		if (res?.length > 0) {
			Array(Math.ceil(res.length / limit))
				.fill('')
				.map((i, k) => {
					resultList.push(res.slice(k * limit, k * limit + limit));
				});
		}
		setTotal(res.length || 0);
		resultList = resultList.flat(1);
		return resultList;
	}, [httpData, filter]);
	useEffect(() => {
		getData();
	}, []);
	return (
		<div className={cn(className, s.tableContainer, s.pr)}>
			{/* <div className={cn(s.df, s.aic, s.jcfe, s.pr10, s.mb20)}>
				<Select
					placeholder="监测结果"
					className={s.item}
					value={[filter.securityStatus]}
					allowClear={true}
					getPopupContainer={triggerNode => triggerNode}
					clearable
					option={[
						{ label: '正常', value: 'safe' },
						{ label: '异常', value: 'warning' },
					]}
					onChange={({ selectedItem }) =>
						handleChangeSearch({
							securityStatus: selectedItem[0] ? selectedItem[0].value : '',
						})
					}
				/>
			</div> */}
			<div>
				<span className={s.spT}>HTTP监测</span>
				{/* <Link
					to={{
						pathname: '/job-manage/aviliable-task',
						search: `filter=${encodeURI(
							JSON.stringify({ target, task_group_type: 'http' })
						)}`,
					}}
				>
					查看任务
				</Link> */}
				<Table
					columns={columns}
					loading={loading}
					key={'HTTP监测' + Math.random().toString(36).slice(-6)}
					className={cn(s.bborderTable)}
					scroll={{
						y: historyPageData.length > 5 ? 235 : false,
						x: 'unset'
					}}
					expandable={{
						expandIcon({ expanded, onExpand, record }) {
							return expanded ? (
								<CaretUpOutlined onClick={e => onExpand(record, e)} style={{ color: '#ccc', width: '10px' }} />
							) : (
								<CaretDownOutlined onClick={e => onExpand(record, e)} style={{ color: '#ccc', width: '10px' }} />
							);
						},
						expandRowByClick: true,
						columnWidth: 50,
						expandedRowRender(record) {
							return (
								<div>
									<p className={cn(s.p0_10, s.primaryColor)}>
										<span
											className={s.cp}
											onClick={() => {
												const settings = cloneDeep(record.task_settings);
												settings.startTime = record.time_info.start_time;
												settings.endTime = record.time_info.end_time;
												settings.taskSessionId = record.task_session_id;
												settings.taskType = record.taskType;
												setTaskSettings(settings);
												setVisible(true);
											}}
										>
											查看任务信息
										</span>
									</p>
									<div className={s.maxH190}>
										<div>
											{record.addition?.detail?.map(i => {
												return (
													<p
														className={cn(s.desItem, {
															[s.pingItem]: record?.taskType === 'ping',
														})}
														key={i}
													>
														<span title={i.area} className={s.itemSp1}>
															监测点：{i.area}
														</span>
														<span title={i.networkDisplayName}>
															监测类型：{i.networkDisplayName}
														</span>
														<span title={i.ip || '- -'}>
															响应服务器IP：{i.ip || '- -'}
															{/* {i.ip ? <CopyBoard text={i.ip} /> : '- -'} */}
														</span>
														{record?.taskType === 'http' && (
															<span title={i.securityStatus === 'error' ? null : i.statusCode}>
																响应状态码：{i.securityStatus === 'error' ? '- -' : i.statusCode}
															</span>
														)}
														<span>总响应时间：{i.securityStatus === 'error' ? '- -' : `${i.totalTime}ms`}</span>
														<span>
															状态：
															{i.securityStatus === 'warning' ? '异常' : i.securityStatus === 'error' ? '节点出错' : '正常'}
														</span>
														<span>
															{i.securityStatus === 'error' ? '- -' : <TaskResult
																securityStatus={i.securityStatus}
																result={{ ...i, endTime: record?.endTime }}
																type="text"
																taskType={record?.taskType}
																withoutIcon={true}
															/>}
														</span>
													</p>
												);
											})}
										</div>
									</div>
								</div>
							);
						},
					}}
					data={historyPageData}
					empty={
						<Empty
							emptyType={checkData('http').img}
							text={checkData('http').text}
							className={s.bd0}
						/>
					}
					pro
				/>
				<div className={cn(s.df, s.mt20, s.jcfe)}>
					{/* {total > 10 && (
						<Pagination
							total={total}
							current={filter.page || 1}
							pageSize={filter.limit || 10}
							showQuickJumper={{ goButton: true }}
							showSizeChanger={true}
							pageSizeOptions={['10', '20']}
							onChange={(page, limit) => {
								handleChangeSearch({ page, limit });
							}}
						/>
					)} */}
				</div>
			</div>
			<div>
				<span className={s.spT}>Ping监测</span>
				{/* <Link
					to={{
						pathname: '/job-manage/aviliable-task',
						search: `filter=${encodeURI(
							JSON.stringify({ target, task_group_type: 'ping' })
						)}`,
					}}
				>
					查看任务
				</Link> */}
				<Table
					columns={columns}
					loading={loading}
					key={'Ping监测'}
					className={cn(s.bborderTable)}
					scroll={{
						y: pingData.length > 5 ? 235 : 'unset',
						x: 'unset'
					}}
					expandable={{
						expandIcon({ expanded, onExpand, record }) {
							return expanded ? (
								<CaretUpOutlined onClick={e => onExpand(record, e)} style={{ color: '#ccc', width: '10px' }} />
							) : (
								<CaretDownOutlined onClick={e => onExpand(record, e)} style={{ color: '#ccc', width: '10px' }} />
							);
						},
						expandRowByClick: true,
						columnWidth: 50,
						expandedRowRender(record) {
							return (
								<div>
									<p className={cn(s.p0_10, s.primaryColor)}>
										<span
											className={s.cp}
											onClick={() => {
												const settings = cloneDeep(record.task_settings);
												settings.startTime = record.time_info.start_time;
												settings.endTime = record.time_info.end_time;
												settings.taskSessionId = record.task_session_id;
												settings.taskType = record.taskType;
												setTaskSettings(settings);
												setVisible(true);
											}}
										>
											查看任务信息
										</span>
									</p>
									<div className={s.maxH190}>
										<div>
											{record.addition?.detail?.map(i => {
												return (
													<p
														className={cn(s.desItem, {
															[s.pingItem]: record?.taskType === 'ping',
														})}
														key={i}
													>
														<span title={i.area} className={s.itemSp1}>
															监测点：{i.area}
														</span>
														<span title={i.networkDisplayName}>
															监测类型：{i.networkDisplayName}
														</span>
														<span title={i.ip || '- -'}>
															响应服务器IP：{i.ip || '- -'}
														</span>
														{record?.taskType === 'http' && (
															<span title={i.securityStatus === 'error' ? null : i.statusCode}>
																响应状态码：{i.securityStatus === 'error' ? '- -' : i.statusCode}
															</span>
														)}
														<span>总响应时间：{i.securityStatus === 'error' ? '- -' : `${i.totalTime}ms`}</span>
														<span>
															状态：
															{i.securityStatus === 'warning' ? '异常' : i.securityStatus === 'error' ? '节点出错' : '正常'}
														</span>
														<span>
															{i.securityStatus === 'error' ? '- -' : <TaskResult
																securityStatus={i.securityStatus}
																result={{ ...i, endTime: record?.endTime }}
																type="text"
																taskType={record?.taskType}
																withoutIcon={true}
															/>}
														</span>
													</p>
												);
											})}
										</div>
									</div>
								</div>
							);
						},
					}}
					data={pingData}
					empty={
						<Empty
							emptyType={checkData('ping').img}
							text={checkData('ping').text}
							className={s.bd0}
						/>
					}
					pro
				/>
				<div className={cn(s.df, s.mt20, s.jcfe)}>
					{/* {total > 10 && (
						<Pagination
							total={total}
							current={filter.page || 1}
							pageSize={filter.limit || 10}
							showQuickJumper={{ goButton: true }}
							showSizeChanger={true}
							pageSizeOptions={['10', '20']}
							onChange={(page, limit) => {
								handleChangeSearch({ page, limit });
							}}
						/>
					)} */}
				</div>
			</div>
			<Dialog
				title={
					<div className={cn(s.df, s.aic)}>
						任务信息
						<Tooltip
							overlay="以下配置为该资产当次任务检测时设置的参数。"
							placement="top"
						>
							<Icon
								className={cn(s.cp, s.ml5, s.primaryColor)}
								type="question"
							/>
						</Tooltip>
					</div>
				}
				className={s.w520}
				visible={visible}
				confirmText="关闭"
				onhide={() => setVisible(false)}
				cancelText=""
			>
				<div className={cn(s.p20, s.noStyle)}>
					<p className={s.circle}>
						{taskSettings?.taskType === 'http' ? 'HTTP' : 'Ping'}监测参数
					</p>
					<Form name="basic" labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
						<Form.Item label="监测节点">
							<div className={s.pt5}>
								<p>
									IPv4：
									{taskContent(
										taskSettings?.collect.area,
										aviliableNode?.v4_area?.reduce((t, i) => {
											const item = cloneDeep(i);
											if (item.enable) {
												delete item.enable;
												t[Object.keys(item)[0]] = item[Object.keys(item)[0]];
											}
											return t;
										}, {})
									)}
								</p>
								<p>
									IPv6：
									{taskContent(
										taskSettings?.collect.area_ipv6,
										aviliableNode?.v6_area?.reduce((t, i) => {
											const item = cloneDeep(i);
											if (item.enable) {
												delete item.enable;
												t[Object.keys(item)[0]] = item[Object.keys(item)[0]];
											}
											return t;
										}, {})
									)}
								</p>
							</div>
						</Form.Item>
						<Form.Item label="监测频率">
							{timeChange(taskSettings?.interval)}
						</Form.Item>
						{taskSettings?.taskType === 'http' && (
							<>
								<Form.Item label="HTTP请求方法">
									{taskSettings?.collect?.method?.toUpperCase()}
								</Form.Item>
								<Form.Item label="HTTP请求信息">
									{Object.keys(taskSettings?.collect?.header || {}).length > 0
										? Object.keys(taskSettings?.collect?.header).map(key => {
												return `${key}：${taskSettings?.collect?.header[key]}`;
										  })
										: '- -'}
								</Form.Item>
								{['post', 'put'].includes(taskSettings?.collect?.method) && (
									<Form.Item label="提交内容">
										{taskSettings?.collect?.payload || '- -'}
									</Form.Item>
								)}
								<Form.Item label="重定向次数">
									允许页面最多跳转{taskSettings?.collect?.redirect}次
								</Form.Item>
							</>
						)}
					</Form>
					<p className={cn(s.circle, s.mt20)}>监测时间详情</p>
					<Form name="basic" labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
						<Form.Item label="监测开始时间">
							{moment(taskSettings?.startTime).format('YYYY-MM-DD HH:mm:ss')}
						</Form.Item>
						<Form.Item label="监测结束时间">
							{moment(taskSettings?.endTime).format('YYYY-MM-DD HH:mm:ss')}
						</Form.Item>
						<Form.Item label="监测耗时">
							{timeChange(
								new Date(taskSettings?.endTime).getTime() -
									new Date(taskSettings?.startTime).getTime()
							)}
						</Form.Item>
						<Form.Item label="监测任务ID">
							{taskSettings?.taskSessionId}
						</Form.Item>
					</Form>
				</div>
			</Dialog>
		</div>
	);
}

InfoTable.propTypes = {
	tasks: PropTypes.any,
	className: PropTypes.string,
	data: PropTypes.arrayOf(
		PropTypes.shape({
			node: PropTypes.string,
			statusCode: PropTypes.number,
			respTime: PropTypes.number,
			securityStatus: PropTypes.string,
		})
	),
};
InfoTable.defaultProps = {
	className: '',
};

export default InfoTable;
